home *** CD-ROM | disk | FTP | other *** search
/ Fritz: All Fritz / All Fritz.zip / All Fritz / FILES / PROGNG_C / TC_XMEM.LZH / TC_XMEM.C < prev    next >
C/C++ Source or Header  |  1987-10-08  |  9KB  |  292 lines

  1. #include <stdio.h>
  2. #include <string.h>
  3.  
  4. /*
  5.    ---------------------------------------------------------------------------
  6.    TC_XMEM.C - This is a short program to demonstrate how to use the XMEM
  7.                function in Turbo C. All it does is take one string, move it
  8.                to extended memory at location 100000 (1 megabyte boundary),
  9.                then takes it from extended memory and places it into a second
  10.                array. As you can see, we do initialize o_message to the test
  11.                string and n_message to nothing, but we never touch any of them
  12.                again until it is time to show you the results of XMEM.
  13.  
  14.            In essence, this is a heck of a roundabout way to do a strcpy,
  15.            but the possibilities for applications are boundless.
  16.  
  17.            There are four statements here that will generate four non-
  18.                portability warnings, particularly between memory models, but
  19.                we ignore them since we are only trying to show how XMEM works.
  20.    ---------------------------------------------------------------------------
  21. */
  22.  
  23. unsigned s_seg,        /* Source data segment */
  24.      d_seg,     /* Destination segment */
  25.      s_off,     /* Source offset       */
  26.      d_off,     /* Destination offset  */
  27.      size;      /* Size, in bytes, of data to transfer */
  28.  
  29. char     *s_meg,     /* Megabyte boundary of source, 0 to 15 */
  30.     *d_meg;     /* Megabyte boundary of destination, 0 to 15 also */
  31.  
  32. /* Note that one of the two must have a value of 0 since XMEM transfers */
  33. /* to/from DOS memory, which is below the 1 megabyte boundary           */
  34.  
  35. int result;         /* Holds return code from XMEM */
  36. int CPU;        /* Holds type of CPU currently in machine */
  37. char VDISK_ON;        /* Used to tell us if VDISK is alive */
  38. unsigned long temp2;     /* For our own temp purposes also */
  39.  
  40. char o_message[36];    /* The source area */
  41. char n_message[36];    /* The destination (target) area */
  42. char v_save[36];    /* Temp area to save VDISK boot sec */
  43.  
  44. /* This is the structure that defines the IBM PC-DOS VDISK boot record */
  45. /* structure. Here is where we get the info to determine if VDISK is   */
  46. /* is installed and how much of extended memory has it already         */
  47. /* allocated to itself.                                                */
  48.  
  49. typedef struct {
  50.     char jump_code[3];        /* Boot jump code, all 0's */
  51.     char vendor_id[8];        /* Should contain "VDISKx.x" */
  52.     int bytes_per_sector;        /* Bytes per sector in ram disk */
  53.     char sectors_per_cluster;    /* Sectors per cluster */
  54.     int reserved_sectors;        /* Number of reserved sectors */
  55.     char fat_copies;        /* Number of FAT copies */
  56.     int dir_entries;        /* Number of root dir entries */
  57.     int num_sectors;        /* Total number of sectors */
  58.     char media;            /* Media descriptor bytes */
  59.     int sectors_per_fat;        /* Sectors occupied by one FAT */
  60.     int sectors_per_track;        /* Number of sectors per track */
  61.     int heads;            /* Number of heads */
  62.     int hidden;            /* Number of hidden sectors */
  63.     int em_start;            /* Starting loc of 1st free area... */
  64.                     /* ...in extended memory/1024 */
  65.     } vdisk_boot_sec;
  66.     
  67. vdisk_boot_sec BOOT_SEC;
  68.  
  69. /* IOADDRESS is used to set port to read/write to             */
  70. /* IODATA    is used to read/write data once port is selected */
  71.  
  72. #define IOADDRESS 0x070
  73. #define IODATA    0x071
  74.  
  75. /* These variables hold the CMOS extended memory size information */
  76.  
  77. int EXT_LO, EXT_HI, EXT_TOTAL;
  78.  
  79. main()
  80. {
  81.  
  82.     printf("TC_XMEM: Demonstration of the XMEM assembly language\n");
  83.     printf("         routine to mode data to/from extended memory\n");
  84.  
  85.     CPU = CPUID();
  86.     if ((CPU != 286) && (CPU != 386))
  87.     {
  88.         result = 99;
  89.         error_handle();
  90.     }
  91.  
  92.     printf("TC_XMEM: CPU is 80%d.\n",CPU);
  93.  
  94. /* Let's see how much extended memory we have, if any... */
  95.  
  96.     EXT_LO = portpeek(0x017);
  97.     EXT_HI = portpeek(0x018);
  98.     EXT_TOTAL = ((EXT_HI << 8) + EXT_LO);
  99.  
  100.     if (EXT_TOTAL > 0)
  101.     {
  102.          printf("TC_XMEM: %dK extended memory installed.\n",EXT_TOTAL);
  103.         printf("         Total memory is %dK.\n",(EXT_TOTAL+1024));
  104.                 printf("         This includes DOS, video, reserved and extended memory.\n");
  105.     }
  106.     else 
  107.     {
  108.         result = 7;
  109.         error_handle();
  110.     }
  111.  
  112. /* At this point we do a quick check of the first few bytes of extended      */
  113. /* ram to find out if VDISK is already in place. We cannot check for any     */
  114. /* other ram disks because VDISK is the only one that we have documentation  */
  115. /* for and it's the only one (that we know) that tells us where in extended  */
  116. /* memory the ram disk buffers end.                                          */
  117.  
  118. /* Source is address 100000, location of boot record of VDISK if installed */
  119.  
  120.     s_seg = s_off = 0;
  121.     s_meg = 1;
  122.  
  123. /* Destination maps into the vdisk_boot_sec structure to decode the meaning */
  124. /* of life in the VDISK fast lane... */
  125.  
  126.     d_seg = _DS;    /* small/tiny memory model only! */
  127.     d_off = &BOOT_SEC.jump_code[0];
  128.     d_meg = 0;
  129.  
  130. /* Size is size of boot record in bytes, 32 bytes */
  131.  
  132.     size = 32;
  133.  
  134. /* All set, bring it down and let's take a look at it! */
  135.  
  136.     result = XMEM(s_seg,s_off,s_meg,d_seg,d_off,d_meg,size);
  137.  
  138. /* Check for error */
  139.  
  140.     if (result > 0) error_handle();
  141.  
  142. /* No errors. First, let's see if we have a VDISK */
  143.  
  144.  
  145.     VDISK_ON = strstr(BOOT_SEC.vendor_id,"VDISK");
  146.     if (VDISK_ON != 0)
  147.     {
  148.         printf("TC_XMEM: VDISK is installed.\n");
  149.         printf("         VDISK buffer(s) end at %uK\n",BOOT_SEC.em_start);
  150.         if (BOOT_SEC.em_start >= (EXT_TOTAL+1024))
  151.         {
  152.             printf("         VDISK has allocated all extended memory.\n");
  153.         }
  154.         printf("     Saving VDISK Boot Record.\n");
  155.         d_off = &v_save;
  156.         size = 36;
  157.         result = XMEM(s_seg,s_off,s_meg,d_seg,d_off,d_meg,size);
  158.     }
  159.     
  160.  
  161.     strcpy(o_message,"This is a test of the XMEM function.");
  162.     strcpy(n_message,"\0x00");
  163.  
  164.     printf("TC_XMEM: Source and target initialized.\n");
  165.     printf("         Source area contains:\n");
  166.     printf("         [ %s ]\n",o_message);
  167.     printf("         Target area contains:\n");
  168.     printf("     [ %s ]\n",n_message);
  169.  
  170. /* Since we are working with the small memory model here, we know that the */
  171. /* source string data is located in segment _DATA, which is grouped under  */
  172. /* DGROUP, whose value is in the DS: segment. For other memory models, you */
  173. /* must decode any "far" pointers to determine what segment the source     */
  174. /* is located in.                                                          */
  175.  
  176.     s_seg = _DS;    /* tiny/small memory model only! */
  177.  
  178. /* source offset is the address of o_message (tiny,small memory models) */
  179.  
  180.     s_off = &o_message;
  181.  
  182. /* Source is in DOS memory */
  183.  
  184.     s_meg = 0;
  185.  
  186. /* Destination setup, move string to address 10000:0 */
  187.  
  188.     d_seg = d_off = 0;
  189.     d_meg = 1;
  190.  
  191. /* Transferring 36 bytes, length of string */
  192.  
  193.     size  = 36;
  194.  
  195. /* Setup completed, call XMEM and send the string to extended memory */
  196. /* storage.                                                          */
  197.  
  198.     result = XMEM(s_seg,s_off,s_meg,d_seg,d_off,d_meg,size);
  199.  
  200. /* Check to see if any errors detected. */
  201.  
  202.     if (result > 0) error_handle();
  203.  
  204. /* No errors, say so */
  205.  
  206.     printf("TC_XMEM: Move from low to high mem successful.\n");
  207.  
  208. /* Ok, now we set source to 100000, where data is now stored, and target */
  209. /* to the location where we have allocated space for the string          */
  210.  
  211.     s_seg = s_off = 0;
  212.     s_meg = 1;
  213.     d_seg = _DS;        /* tiny/small memory model only! */
  214.     d_off = &n_message;
  215.     d_meg = 0;
  216.  
  217. /* Heads up, data coming down! */
  218.  
  219.     result = XMEM(s_seg,s_off,s_meg,d_seg,d_off,d_meg,size);
  220.  
  221. /* Check to see if we have any errors */
  222.  
  223.     if (result > 0) error_handle();
  224.  
  225. /* Everything seems ok, say so, then print both strings to prove that */
  226. /* we actually copied the data */
  227.  
  228.     printf("TC_XMEM: Move from high to low mem successful.\n");
  229.     printf("         Source area contains:\n");
  230.     printf("         [ %s ]\n",o_message);
  231.     printf("         Target area contains:\n");
  232.     printf("     [ %s ]\n",n_message);
  233.  
  234. /* If VDISK is installed we now have to restore the boot sector in */
  235. /* extended RAM so as to keep everything in working condition...   */
  236.  
  237.     if (VDISK_ON != 0)
  238.     {
  239.         printf("         Restoring VDISK Boot Sector.\n");
  240.         s_seg = _DS;
  241.         s_meg = 0;
  242.         s_off = &v_save;
  243.         d_seg = d_off = 0;
  244.         d_meg = 1;
  245.         size = 36;
  246.         result = XMEM(s_seg,s_off,s_meg,d_seg,d_off,d_meg,size);
  247.         if (result > 0) error_handle();
  248.     }
  249.  
  250.     printf("TC_XMEM: Done.\n");
  251.  
  252.     exit(0);
  253. }
  254.  
  255. /* This is our error handler */
  256.  
  257. error_handle()
  258. {
  259.     printf("\aERROR  : ");
  260.     switch (result)
  261.     {
  262.         case 1 : printf("Memory parity error.\n");
  263.              break;
  264.         case 2 : printf("Exception interrupt error.\n");
  265.              break;
  266.         case 3 : printf("8042 slave CPU error.\n");
  267.              break;
  268.         case 5 : printf("Programming error, bounds.\n");
  269.              break;
  270.         case 6 : printf("Not enough extended memory available.\n");
  271.              break;
  272.         case 7 : printf("No extended memory installed.\n");
  273.              break;
  274.         case 99: printf("Program needs 80286 or 80386 CPU.\n");
  275.              break;
  276.         default: printf("Unknown error.\n");
  277.     }
  278.     exit(result);
  279. }
  280.  
  281. /* ------------------------------------------------------------------- */
  282. /* This routine returns the current value in CMOS ram for the location */
  283. /* passed to the function in the variable "location".                  */
  284. /* ------------------------------------------------------------------- */
  285.  
  286. portpeek(location)
  287. unsigned int location;
  288. {
  289.        outportb(IOADDRESS,location);
  290.        return(inportb(IODATA));
  291. }
  292.